#include <gtk/gtk.h>
#include <stdio.h>

#include "gtkutils.h"
// #include "FinalC.h"
#include "FinalCType/String.h"
#include "FinalCType/File.h"

#include "cjsonutils.h"

#include "fileutils.h"
#include "commandutils.h"

void sayHello() {
    printf("hello word\n");
}

GtkSelectionModel* createSelectionModel() {
    // gtk_selection_model
    return NULL;
}
GtkListItemFactory* createItemFactory() {
return NULL;
}
GtkListView* createListView() {
    GtkSelectionModel *model;
    GtkListItemFactory *factory;
    GtkListView *list_view = (GtkListView*)gtk_list_view_new(model, factory);
    return NULL;
}


FinalC_Object_Define(Entry_TextView) {
    GtkTreeModel *combo_model;
    GtkComboBox *combo_select;
    GtkEntryBuffer *entry_buffer;
    GtkTextBuffer *text_buffer;
    File *config;
};

FinalC_Object_Create_Size(Entry_TextView)

// /home/user/.gtk4-gui-config/code-snippets.json

#define GTK_GUI_CONFIG ".gtk4-gui-config"
#define CODE_SNIPPET_CONFIG "code-snippets.json"

void load_config(Entry_TextView *etv) {
    INFO_LOG("载入配置文件: %s", etv->config->path);

}

createTreeModelFunc(load_config_tree) {
    GtkListStore *store = createListStore(1, G_TYPE_STRING, NULL);
    return convTreeModel(store);
}

createSignalObjectFunc(clicked_action, Entry_TextView) {
    printf("配置文件路径：%s\n", user_data->config->path->value);

    // 操作时间
    char outbuffer[1000] = {0};
    getCmdStdoutLine("date", outbuffer);


    // gtk4 ------------------------------------ start
    GtkTextIter start, end;
    gtk_text_buffer_get_start_iter(user_data->text_buffer, &start);
    gtk_text_buffer_get_end_iter(user_data->text_buffer, &end);
    
    const char * entry_text = entryBufferGetText(user_data->entry_buffer);
    char * textview_text = textBufferGetText(user_data->text_buffer, &start, &end, false);
    // gtk4 ------------------------------------ end

    // 构建准备提交内容 String
    String *title = createStringWith_copy_cstr(entry_text);
    String *content = createStringWith_cstr(textview_text);


    // 使用 FinalC 规则下的 String 对象，从配置文件读取并构建为对象
    String *json_str = NULL;
    
    // 初始化文件信息
    fileLoadInfo(user_data->config);

    // 如果文件存在 - 尝试读取到 sjson
    if (user_data->config->exists) {
        json_str = fileReadToString(user_data->config);
        printf("文件存在：读取到 %d 字节\n", json_str->len);
    }

    // json 对象构建
    cJson config = NULL;
    cJson snippets = NULL;
    // 通过 sjson 构建为 Json 对象(检查已读取长度String，检查构建Json是否成功)
    if (json_str->len && (config = toJsonObject(json_str->value))) { 
        snippets = getObjectItem(config, "snippets");  // 如果构建成功将获取 snippet 容器
    } else {
        config = createJsonObject();                   // 未能构建成功将创建对象(例如不存在json) - 将补全基本内容结构
        
        addStringToObject(config, "createTime", outbuffer);
        
        snippets = addArrayToObject(config, "snippets"); // 创建 snippet 容器结构
    }
    deleteString(json_str); // 删除 String


    // 在容器中增加一条 snippet
    if (snippets) {
        cJson snippet = createJsonObject();
        addStringToObject(snippet, "time", outbuffer);
        addStringToObject(snippet, "title", title->value);
        addStringToObject(snippet, "snippet", content->value);
        addItemToArray(snippets, snippet);
    }
    deleteString(title);
    deleteString(content);

    // 将Json对象转为json字符串，并构建为 String 对象
    json_str = createStringWith_cstr(toStringJson(config));

    fileWriteWithString(user_data->config, json_str);

    deleteString(json_str); // 删除 String 对象, 释放 String 并释放指向内存(json字符串)
    deleteJsonObject(config); // 删除 Json 对象
}

static void activate(GtkApplication *app, gpointer user_data) {
    GtkWindow *window;

    window = createWindowWithTitleSize(app, "gtk-code-snippets", 800, 400);

    Entry_TextView *etv = createEntry_TextView();
    etv->combo_model = load_config_tree();
    etv->combo_select = createComboBoxWithModel(etv->combo_model);
    etv->entry_buffer = createEntryBuffer();
    etv->text_buffer = createTextBuffer(NULL);


// 初始版
// ┌──────────────────────────────────────────────────────────────────────────────┐
// │     String *path = createStringWith_copy_cstr(getenv("HOME"));               │
// │     stringAppend_cstr(path, "/" GTK_GUI_CONFIG "/" CODE_SNIPPET_CONFIG);     │
// │     etv->config = createFileWithStringAfter(path, deleteString);             │
// │     deleteString(path);                                                      │
// └──────────────────────────────────────────────────────────────────────────────┘

// 终版：After规则定义：
            // 1. 对象After规则(使用规则提供定义符)
            // 2. 使用After规则(after容器定义)
            // 3. 执行After规则(容器执行)
    etv->config = createFileWithStringAfter(
                    stringAppend_cstr(
                            createStringWith_copy_cstr(getenv("HOME")), 
                            "/" GTK_GUI_CONFIG "/" CODE_SNIPPET_CONFIG
                    ),
                    deleteString);
    

    GtkBox *mainbox = createBoxWithVerticalMarginAppends(5, 5,
        createBoxWithHorizntalMarginAlignAppends(5, 5, ACENTER, 
            createLabel("描述:"), 
            createEntryWithEntryBuffer(etv->entry_buffer), 
            createButtonAction(etv, "提交", clicked_action), 
            NULL
        ), 
        createBoxWithHorizntalMarginExpandAppends(5, 5, true,
            gtk_list_view_new(NULL, NULL),
            createWidgetHorizntalExpand(createWidgetVerticalExpand(createTextViewWithTextBuffer(etv->text_buffer), true), true), 
            NULL
        ),
        NULL
    );

    setWindowChild(window, mainbox);
    showWindow(window);
}

int	main(int argc, char **argv) {

    GtkApplication *app;
    int status;

    app = createApplicationConnectActivate("gtk.example.template", 
                                G_APPLICATION_FLAGS_NONE, activate);

    status = runApplication(app, argc, argv);
    objectUnref(app);

    return status;
}

